<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RocketMQ消息分类艺术：Topic与Tag深度解析</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
            background-color: #f8f9fa;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: #2d3748;
        }
        .hero {
            background: linear-gradient(135deg, #6b46c1 0%, #553c9a 100%);
        }
        .card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }
        .feature-icon {
            background: linear-gradient(135deg, #4299e1 0%, #3182ce 100%);
        }
        .comparison-table {
            border-collapse: separate;
            border-spacing: 0;
            border-radius: 8px;
            overflow: hidden;
        }
        .comparison-table th, .comparison-table td {
            padding: 12px 16px;
            text-align: left;
        }
        .comparison-table thead th {
            background-color: #4299e1;
            color: white;
        }
        .comparison-table tbody tr:nth-child(odd) {
            background-color: #f7fafc;
        }
        .comparison-table tbody tr:nth-child(even) {
            background-color: #edf2f7;
        }
        .comparison-table tbody tr:hover {
            background-color: #ebf8ff;
        }
        .section-divider {
            position: relative;
            height: 80px;
            overflow: hidden;
        }
        .section-divider svg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        .highlight-box {
            border-left: 4px solid #4299e1;
            background-color: #f7fafc;
        }
        .topic-tag-badge {
            display: inline-block;
            padding: 4px 10px;
            border-radius: 16px;
            font-size: 0.85rem;
            font-weight: 500;
        }
        .topic-badge {
            background-color: #9f7aea;
            color: white;
        }
        .tag-badge {
            background-color: #4299e1;
            color: white;
        }
        .mermaid-container {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero text-white py-20 px-4">
        <div class="container mx-auto max-w-5xl">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-1/2 mb-10 md:mb-0">
                    <span class="inline-block bg-white bg-opacity-20 px-4 py-2 rounded-full mb-4 text-sm font-medium">RocketMQ 消息中间件</span>
                    <h1 class="text-4xl md:text-5xl font-bold leading-tight mb-6">消息分类的艺术：<br>Topic与Tag深度解析</h1>
                    <p class="text-xl opacity-90 mb-8">探索RocketMQ中Topic和Tag的设计哲学、使用场景与最佳实践</p>
                    <div class="flex space-x-4">
                        <a href="#topic" class="bg-white text-indigo-700 px-6 py-3 rounded-lg font-medium hover:bg-opacity-90 transition">Topic详解</a>
                        <a href="#tag" class="bg-white bg-opacity-20 px-6 py-3 rounded-lg font-medium hover:bg-opacity-30 transition">Tag详解</a>
                    </div>
                </div>
                <div class="md:w-1/2">
                    <div class="mermaid-container bg-white bg-opacity-10 backdrop-filter backdrop-blur-sm rounded-xl p-6">
                        <div class="mermaid">
                            graph TD
                                A[RocketMQ 消息分类] --> B[Topic 一级分类]
                                A --> C[Tag 二级分类]
                                B --> D[订单Topic]
                                B --> E[支付Topic]
                                B --> F[库存Topic]
                                D --> G[创建订单Tag]
                                D --> H[取消订单Tag]
                                E --> I[支付成功Tag]
                                E --> J[支付失败Tag]
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Topic Section -->
    <section id="topic" class="py-16 px-4 bg-white">
        <div class="container mx-auto max-w-5xl">
            <div class="text-center mb-16">
                <span class="topic-badge topic-tag-badge mb-4">Topic</span>
                <h2 class="text-3xl md:text-4xl font-bold mb-4">Topic的概念和作用</h2>
                <p class="text-xl text-gray-600 max-w-3xl mx-auto">消息的一级分类单位，实现业务隔离与物理存储分离</p>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-16">
                <div class="card p-8 rounded-xl border border-gray-100">
                    <div class="feature-icon w-12 h-12 rounded-xl flex items-center justify-center text-white mb-6">
                        <i class="fas fa-layer-group text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-4">Topic的基本概念</h3>
                    <p class="text-gray-700">Topic是RocketMQ中消息的一级分类，是生产者发送消息和消费者订阅消息的基本单位。在RocketMQ中，所有消息都必须归属于某个Topic。</p>
                </div>

                <div class="card p-8 rounded-xl border border-gray-100">
                    <div class="feature-icon w-12 h-12 rounded-xl flex items-center justify-center text-white mb-6">
                        <i class="fas fa-server text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-4">Topic的物理结构</h3>
                    <ul class="space-y-3 text-gray-700">
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <span>一个Topic可以跨多个Broker存储</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <span>每个Broker上的Topic被划分为多个读写队列(MessageQueue)</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <span>Topic的路由信息由NameServer管理</span>
                        </li>
                    </ul>
                </div>
            </div>

            <h3 class="text-2xl font-bold mb-6">Topic的核心作用</h3>
            <div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
                <div class="card p-6 rounded-lg bg-indigo-50 border border-indigo-100">
                    <div class="text-indigo-600 mb-3">
                        <i class="fas fa-tags text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">消息分类</h4>
                    <p class="text-sm text-gray-700">按业务领域划分消息，如订单消息、用户消息、日志消息等</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-50 border border-indigo-100">
                    <div class="text-indigo-600 mb-3">
                        <i class="fas fa-user-lock text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">订阅隔离</h4>
                    <p class="text-sm text-gray-700">不同消费者组可以订阅不同Topic，消费者只能消费其订阅的Topic中的消息</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-50 border border-indigo-100">
                    <div class="text-indigo-600 mb-3">
                        <i class="fas fa-shield-alt text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">权限控制</h4>
                    <p class="text-sm text-gray-700">可基于Topic进行权限控制，限制生产者和消费者的访问权限</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-50 border border-indigo-100">
                    <div class="text-indigo-600 mb-3">
                        <i class="fas fa-tachometer-alt text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">性能调优</h4>
                    <p class="text-sm text-gray-700">可针对不同Topic设置不同的队列数，高并发Topic可配置更多队列</p>
                </div>
            </div>

            <div class="bg-blue-50 p-6 rounded-xl highlight-box mb-12">
                <h4 class="font-bold text-lg mb-3 flex items-center">
                    <i class="fas fa-lightbulb text-yellow-500 mr-2"></i>
                    Topic设计建议
                </h4>
                <p class="text-gray-700">Topic划分应以业务域为核心，避免过度细分。建议将业务相关性高、处理方式相似的消息归入同一Topic，通过队列数量来调节并发能力。例如电商系统可以按"订单"、"支付"、"库存"等业务域划分Topic。</p>
            </div>

            <div class="mermaid-container mb-12">
                <div class="mermaid">
                    sequenceDiagram
                        participant P as Producer
                        participant N as NameServer
                        participant B as Broker
                        P->>N: 获取Topic路由信息
                        N-->>P: 返回Topic路由(包含Broker和队列信息)
                        P->>B: 根据路由发送消息到指定队列
                        B->>B: 存储消息到CommitLog
                        Note right of B: Topic决定消息的<br>物理存储位置<br>和队列分配
                </div>
            </div>
        </div>
    </section>

    <!-- Divider -->
    <div class="section-divider bg-white text-indigo-600">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
            <path d="M1200 120L0 16.48 0 0 1200 0 1200 120z" fill="currentColor"></path>
        </svg>
    </div>

    <!-- Tag Section -->
    <section id="tag" class="py-16 px-4 bg-indigo-600 text-white">
        <div class="container mx-auto max-w-5xl">
            <div class="text-center mb-16">
                <span class="tag-badge topic-tag-badge mb-4">Tag</span>
                <h2 class="text-3xl md:text-4xl font-bold mb-4">Tag的使用方式和优势</h2>
                <p class="text-xl text-indigo-100 max-w-3xl mx-auto">消息的二级分类单位，实现业务内的精细过滤与灵活扩展</p>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-16">
                <div class="card p-8 rounded-xl border border-indigo-500 bg-indigo-700">
                    <div class="feature-icon w-12 h-12 rounded-xl flex items-center justify-center text-white mb-6">
                        <i class="fas fa-tag text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-4">Tag的基本概念</h3>
                    <p class="text-indigo-100">Tag是RocketMQ中消息的二级分类，附加在Topic之上，用于在同一Topic下进一步区分不同类型的消息。</p>
                </div>

                <div class="card p-8 rounded-xl border border-indigo-500 bg-indigo-700">
                    <div class="feature-icon w-12 h-12 rounded-xl flex items-center justify-center text-white mb-6">
                        <i class="fas fa-code text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-4">Tag的实现方式</h3>
                    <ul class="space-y-3 text-indigo-100">
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-300 mt-1 mr-2"></i>
                            <span>Tag作为消息的一个属性字段存储</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-300 mt-1 mr-2"></i>
                            <span>物理上Tag与消息体一起存储在CommitLog中</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-300 mt-1 mr-2"></i>
                            <span>不会像Topic那样创建物理队列，只是逻辑分类</span>
                        </li>
                    </ul>
                </div>
            </div>

            <h3 class="text-2xl font-bold mb-6">Tag的核心优势</h3>
            <div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
                <div class="card p-6 rounded-lg bg-indigo-700 border border-indigo-600">
                    <div class="text-blue-300 mb-3">
                        <i class="fas fa-filter text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">精细分类</h4>
                    <p class="text-sm text-indigo-100">在一个Topic内进行更细粒度的消息分类</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-700 border border-indigo-600">
                    <div class="text-blue-300 mb-3">
                        <i class="fas fa-search-minus text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">消费过滤</h4>
                    <p class="text-sm text-indigo-100">消费者可按Tag订阅，只接收感兴趣的消息</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-700 border border-indigo-600">
                    <div class="text-blue-300 mb-3">
                        <i class="fas fa-project-diagram text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">降低复杂度</h4>
                    <p class="text-sm text-indigo-100">避免创建过多Topic导致的管理复杂性</p>
                </div>
                <div class="card p-6 rounded-lg bg-indigo-700 border border-indigo-600">
                    <div class="text-blue-300 mb-3">
                        <i class="fas fa-plus-circle text-2xl"></i>
                    </div>
                    <h4 class="font-bold mb-2">灵活扩展</h4>
                    <p class="text-sm text-indigo-100">新增Tag无需变更系统配置</p>
                </div>
            </div>

            <div class="bg-indigo-700 p-6 rounded-xl border border-indigo-600 mb-12">
                <h4 class="font-bold text-lg mb-3 flex items-center">
                    <i class="fas fa-lightbulb text-yellow-300 mr-2"></i>
                    Tag设计建议
                </h4>
                <p class="text-indigo-100">Tag应基于业务操作类型设计，通常对应业务领域内的各种操作行为。例如在"订单Topic"下，可以设计"create"、"pay"、"cancel"等Tag来区分不同类型的订单消息。Tag名称应保持简洁明了，建议使用小写英文单词或缩写。</p>
            </div>

            <div class="mermaid-container bg-indigo-700 border border-indigo-600 mb-12">
                <div class="mermaid">
                    sequenceDiagram
                        participant C as Consumer
                        participant B as Broker
                        C->>B: 订阅Topic并指定Tag(如"pay")
                        B->>B: 过滤消息(只保留Tag="pay"的消息)
                        B-->>C: 仅返回匹配Tag的消息
                        Note right of B: Tag过滤可在Broker端<br>或Consumer端进行<br>减少网络传输和处理开销
                </div>
            </div>
        </div>
    </section>

    <!-- Divider -->
    <div class="section-divider bg-indigo-600 text-white">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
            <path d="M1200 120L0 16.48 0 0 1200 0 1200 120z" fill="currentColor"></path>
        </svg>
    </div>

    <!-- Comparison Section -->
    <section class="py-16 px-4 bg-white">
        <div class="container mx-auto max-w-5xl">
            <div class="text-center mb-16">
                <div class="inline-flex space-x-4 mb-4">
                    <span class="topic-badge topic-tag-badge">Topic</span>
                    <span class="tag-badge topic-tag-badge">Tag</span>
                </div>
                <h2 class="text-3xl md:text-4xl font-bold mb-4">Topic和Tag对比分析</h2>
                <p class="text-xl text-gray-600 max-w-3xl mx-auto">了解它们的差异，做出更明智的设计决策</p>
            </div>

            <div class="overflow-x-auto mb-12">
                <table class="comparison-table w-full">
                    <thead>
                        <tr>
                            <th class="w-1/4">特性</th>
                            <th class="w-2/5">Topic</th>
                            <th class="w-2/5">Tag</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>分类级别</td>
                            <td>一级分类</td>
                            <td>二级分类</td>
                        </tr>
                        <tr>
                            <td>物理隔离</td>
                            <td>有（独立队列）</td>
                            <td>无（逻辑分类）</td>
                        </tr>
                        <tr>
                            <td>存储影响</td>
                            <td>创建独立的物理队列</td>
                            <td>不创建额外存储结构</td>
                        </tr>
                        <tr>
                            <td>路由管理</td>
                            <td>由NameServer管理路由</td>
                            <td>无需路由管理</td>
                        </tr>
                        <tr>
                            <td>订阅方式</td>
                            <td>必须明确订阅Topic</td>
                            <td>可在Topic下按Tag过滤订阅</td>
                        </tr>
                        <tr>
                            <td>扩展成本</td>
                            <td>较高（需创建物理资源）</td>
                            <td>较低（只需标记消息）</td>
                        </tr>
                        <tr>
                            <td>过滤位置</td>
                            <td>消息投递时（Broker端）</td>
                            <td>消息消费时（可在Broker或Consumer端）</td>
                        </tr>
                        <tr>
                            <td>适用场景</td>
                            <td>不同业务领域、需物理隔离</td>
                            <td>同一业务领域内的子分类</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h3 class="text-2xl font-bold mb-6">典型应用场景</h3>
            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div class="card p-6 rounded-xl border border-gray-100">
                    <h4 class="font-bold text-xl mb-4 flex items-center">
                        <span class="topic-badge topic-tag-badge mr-3">Topic</span>
                        <span>适用场景</span>
                    </h4>
                    <ul class="space-y-3 text-gray-700">
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-indigo-500 mt-2 mr-2"></i>
                            <span>不同业务领域：订单系统、库存系统、支付系统各自使用独立Topic</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-indigo-500 mt-2 mr-2"></i>
                            <span>消息量级差异大：高频交易消息和一般通知消息应使用不同Topic</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-indigo-500 mt-2 mr-2"></i>
                            <span>消息存储策略不同：核心业务数据和一般日志消息</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-indigo-500 mt-2 mr-2"></i>
                            <span>隔离性要求高：敏感业务操作和普通业务操作</span>
                        </li>
                    </ul>
                </div>
                <div class="card p-6 rounded-xl border border-gray-100">
                    <h4 class="font-bold text-xl mb-4 flex items-center">
                        <span class="tag-badge topic-tag-badge mr-3">Tag</span>
                        <span>适用场景</span>
                    </h4>
                    <ul class="space-y-3 text-gray-700">
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-blue-500 mt-2 mr-2"></i>
                            <span>同一业务的不同操作类型：用户Topic下的注册、登录、注销等操作</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-blue-500 mt-2 mr-2"></i>
                            <span>消费端按需订阅：商品Topic下，价格服务关注价格变更Tag，库存服务关注库存变更Tag</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-blue-500 mt-2 mr-2"></i>
                            <span>消息类型动态扩展：营销系统中不断新增的活动类型</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-circle text-xs text-blue-500 mt-2 mr-2"></i>
                            <span>消息量相近的子分类：通知服务中的邮件通知、短信通知、站内信通知</span>
                        </li>
                    </ul>
                </div>
            </div>

            <div class="bg-blue-50 p-6 rounded-xl highlight-box">
                <h4 class="font-bold text-lg mb-3 flex items-center">
                    <i class="fas fa-gem text-indigo-600 mr-2"></i>
                    最佳实践建议
                </h4>
                <div class="space-y-4">
                    <div class="flex items-start">
                        <div class="flex-shrink-0 h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center mr-3">
                            <i class="fas fa-ruler-vertical text-indigo-600"></i>
                        </div>
                        <p class="text-gray-700"><strong>合理设计粒度</strong>：Topic划分不宜过细，避免系统复杂度增加。一般按业务域划分Topic，业务域内再用Tag细分。</p>
                    </div>
                    <div class="flex items-start">
                        <div class="flex-shrink-0 h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center mr-3">
                            <i class="fas fa-puzzle-piece text-indigo-600"></i>
                        </div>
                        <p class="text-gray-700"><strong>组合使用策略</strong>：Topic用于一级业务分类，Tag用于同一业务内的消息类型区分。如订单系统使用"OrderTopic"，下设"create"、"pay"、"cancel"等Tag。</p>
                    </div>
                    <div class="flex items-start">
                        <div class="flex-shrink-0 h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center mr-3">
                            <i class="fas fa-tachometer-alt text-indigo-600"></i>
                        </div>
                        <p class="text-gray-700"><strong>考虑性能因素</strong>：过多的Topic会增加系统开销，但单个Topic下消息量过大也会影响性能。需根据实际业务量和处理速度平衡Topic和Tag的使用。</p>
                    </div>
                    <div class="flex items-start">
                        <div class="flex-shrink-0 h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center mr-3">
                            <i class="fas fa-map-marked-alt text-indigo-600"></i>
                        </div>
                        <p class="text-gray-700"><strong>前瞻性规划</strong>：Topic结构调整成本高，应预先合理规划。Tag可以灵活添加，便于系统演进。</p>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-12 px-4">
        <div class="container mx-auto max-w-5xl">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-6 md:mb-0">
                    <h3 class="text-xl font-bold mb-2">技术小馆</h3>
                    <a href="http://www.yuque.com/jtostring" class="text-gray-400 hover:text-white transition">http://www.yuque.com/jtostring</a>
                </div>
                <div class="flex space-x-6">
                    <a href="#" class="text-gray-400 hover:text-white transition">
                        <i class="fab fa-github text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition">
                        <i class="fab fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition">
                        <i class="fab fa-linkedin text-xl"></i>
                    </a>
                </div>
            </div>
            <div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-500 text-sm">
                &copy; 2023 技术小馆. All rights reserved.
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            },
            themeVariables: {
                primaryColor: '#E1F0FF',
                primaryBorderColor: '#9f7aea',
                primaryTextColor: '#2d3748',
                lineColor: '#9f7aea'
            }
        });
    </script>
</body>
</html>